package jp.co.tms.internal.webserver;

import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import jp.co.tms.internal.data.ITaskQueue;
import jp.co.tms.internal.lib.soap.SoapStub;
import jp.co.tms.internal.lib.soap.SoapStub.GetTodoTaskList;
import jp.co.tms.internal.lib.soap.SoapStub.GetTodoTaskListResponse;
import jp.co.tms.internal.lib.soap.SoapStub.OnAdded;
import jp.co.tms.internal.lib.soap.SoapStub.OnNormalEnded;
import jp.co.tms.internal.lib.soap.SoapStub.TaskForRunserver;
import jp.co.tms.internal.lib.soap.SoapStub.TaskForRunserverList;
import jp.co.tms.internal.task.IRunTask;
import jp.co.tms.internal.task.ITask;
import jp.co.tms.internal.task.RunTask;

import org.apache.axis2.AxisFault;

public class WebServerManager extends TimerTask{
	// 1 second
	public final static int DEF_SECOND = 1000;
	// 8 seconds
	public final static int DEF_DELAY_TIME    = 8 * DEF_SECOND;
	// 10 seconds.
	public final static int DEF_INTERVAL_TIME = 10 * DEF_SECOND;
	// timer engine.
	private Timer _timer = new Timer();
	// id exchanger. 
	private Map<Integer, UUID> _idMap = new HashMap<Integer, UUID>();
	// id generator.
	private Random _random = new Random();
	// input queue.
	private ITaskQueue _inputQueue;
	// output queue.
	private ITaskQueue _outputQueue;
	
	public WebServerManager(ITaskQueue input, ITaskQueue output){
		this._inputQueue = input;
		this._outputQueue = output;
	}
	
	public boolean start(){
		// start timer.
		_timer.schedule(this, 
				DEF_DELAY_TIME, 
				DEF_INTERVAL_TIME);
		
		// Success.
		return true;
	}
	
	public void run() {
		//
		// 1. Get Input task and call the web service to update the DB. 
		updateEndedTasks();
		//
		// 2. Get the information from web server. 
		updateTaskQueue();
	}
	
	public void stop(){
		_timer.cancel();
	}
	
	protected ITask getNextInputTask(){
		return _inputQueue.poll();
	}
	/*
	 * update the status of task in DB
	 */
	protected void updateEndedTasks(){
		
		try{
			SoapStub ss = new SoapStub();
			while(true){
				ITask inputTask = getNextInputTask();
				if ( inputTask == null)
					break;
				
				if ( inputTask instanceof IRunTask ){
					IRunTask task = (IRunTask)inputTask;
					UUID uuid = _idMap.get(task.getId());
					if (uuid == null){
						continue;
					}
					//
					// update the status of task in db.
					OnNormalEnded ended = new OnNormalEnded();
					ended.setTaskUUID2(uuid.toString());
					ss.onNormalEnded(ended);
					//
					// remove the finished task.
					_idMap.remove(task.getId());
				}	
			}
		}
		catch(AxisFault e){
			e.printStackTrace();
		}
		catch(RemoteException e){
			e.printStackTrace();
		}
	}
	
	/*
	 * Check the task from DB
	 */
	protected void updateTaskQueue(){
		try {
			SoapStub ss = new SoapStub();
			GetTodoTaskListResponse tlr = ss.getTodoTaskList(new GetTodoTaskList());
			if (tlr == null){
				return;
			}
			
			TaskForRunserverList list = tlr.getGetTodoTaskListReturn();
			if (list == null){
				return;
			}
			
			TaskForRunserver[] tasks = list.getTaskList();
			if (tasks == null){
				return;
			}	
			
			for (TaskForRunserver task : tasks){
				//
				// Get the Task Id and UUID
				int taskId = _random.nextInt();
				UUID uuid  = UUID.fromString(task.getTaskUUID());
				//
				// Store the id into map.
				_idMap.put(taskId, uuid);
				//
				// Create a new task.
				IRunTask newTask = new RunTask(
						taskId, 
						task.getLevel(), 
						task.getCommand());
				//
				// Add the task to queue.
				_outputQueue.offer(newTask);
				//
				// change the task's status in db.
				OnAdded added = new OnAdded();
				added.setTaskUUID4(task.getTaskUUID());
				ss.onAdded(added);
			}
		} 
		catch (AxisFault e) {
			e.printStackTrace();
		} 
		catch (RemoteException e) {
			e.printStackTrace();
		}
	}
}
